package com.abc.robot01.activity

import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.*
import android.view.*
import android.widget.ImageView
import android.widget.Toast
import com.alibaba.fastjson.JSONObject
import androidx.annotation.*
import androidx.annotation.IntRange
import androidx.fragment.app.Fragment
//import com.alibaba.fastjson.JSONObject
//import com.bumptech.glide.Glide
//import com.bumptech.glide.load.engine.DiskCacheStrategy
//import com.canbot.u05.R
//import com.canbot.u05.ago
//import com.canbot.u05.bean.MsgType2
//import com.canbot.u05.face.utils.ToastTools
//import com.canbot.u05.fromNow
//import com.canbot.u05.service.StatusBarService
//import com.canbot.u05.socket.MsgSendUtils
//import com.canbot.u05.utils.Logger
import java.io.*
import java.util.*
import kotlin.OptIn
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract

fun Activity.showToast(string: String) {
    this.runOnUiThread {
        val toast = Toast.makeText(this, string, Toast.LENGTH_SHORT)
        toast.setGravity(Gravity.BOTTOM, 0, 0)
        toast.show()
    }
}

fun Activity.showToast(@StringRes resId: Int) {
    showToast(getString(resId))
}

//fun toast(block: () -> String) {
//    ToastTools.getInstance().showText(block())
//}

fun Fragment.showToast(string: String) {
    this.activity?.runOnUiThread {
        val toast = Toast.makeText(this.activity, string, Toast.LENGTH_SHORT)
        toast.setGravity(Gravity.BOTTOM, 0, 0)
        toast.show()
    }
}

fun Fragment.showToast(@StringRes resId: Int) {
    showToast(getString(resId))
}

fun Activity.setResultOK(intent: Intent? = null) {
    if (intent == null) {
        setResult(Activity.RESULT_OK)
    } else {
        setResult(Activity.RESULT_OK, intent)
    }
}

fun Activity.setResultCanceled() {
    setResult(Activity.RESULT_CANCELED)
}

fun Activity.hideBottomUIMenu() {
    window.hide()
}

//fun Activity.showStatusBar() {
//    this.startService(Intent(this, StatusBarService::class.java).putExtra("statusBar", "show"))
//}
//
//fun Activity.hideStatusBar() {
//    this.startService(Intent(this, StatusBarService::class.java).putExtra("statusBar", "hide"))
//}

inline fun <reified C : Activity> Context.startActivity(
    options: Bundle? = null,
    noinline init: Intent.() -> Unit = {}
) {
    val intent = newIntent<C>(this).apply(init)
    startActivity(intent, options)
}

inline fun <reified C : Activity> Context.startActivity(vararg params: Pair<String, Any>) {
    val intent = newIntent<C>(this)
    params.forEach {
        when (val value = it.second) {
            is Int -> intent.putExtra(it.first, value)
            is Long -> intent.putExtra(it.first, value)
            is CharSequence -> intent.putExtra(it.first, value)
            is String -> intent.putExtra(it.first, value)
            is Float -> intent.putExtra(it.first, value)
            is Double -> intent.putExtra(it.first, value)
            is Char -> intent.putExtra(it.first, value)
            is Short -> intent.putExtra(it.first, value)
            is Boolean -> intent.putExtra(it.first, value)
            is Serializable -> intent.putExtra(it.first, value)
            is Bundle -> intent.putExtra(it.first, value)
            is Parcelable -> intent.putExtra(it.first, value)
            is Array<*> -> when {
                value.isArrayOf<CharSequence>() -> intent.putExtra(it.first, value)
                value.isArrayOf<String>() -> intent.putExtra(it.first, value)
                value.isArrayOf<Parcelable>() -> intent.putExtra(it.first, value)
            }
            is IntArray -> intent.putExtra(it.first, value)
            is LongArray -> intent.putExtra(it.first, value)
            is FloatArray -> intent.putExtra(it.first, value)
            is DoubleArray -> intent.putExtra(it.first, value)
            is CharArray -> intent.putExtra(it.first, value)
            is ShortArray -> intent.putExtra(it.first, value)
            is BooleanArray -> intent.putExtra(it.first, value)
        }
    }
    startActivity(intent)
}

inline fun <reified C : Activity> Activity.startActivityAndFinish(
    options: Bundle? = null,
    noinline init: Intent.() -> Unit = {}
) {
    val intent = newIntent<C>(this).apply(init)
    startActivity(intent, options)
    finish()
}

inline fun <reified C : Activity> Activity.startActivityForResult(
    requestCode: Int = -1,
    options: Bundle? = null,
    noinline init: Intent.() -> Unit = {}
) {
    val intent = newIntent<C>(this).apply(init)
    startActivityForResult(intent, requestCode, options)
}

inline fun <reified T : Any> newIntent(context: Context): Intent {
    return Intent(context, T::class.java)
}

private fun Window.hide() {
    this.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
    this.decorView.setOnSystemUiVisibilityChangeListener {
        val uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
                // 布局位于状态栏下方
                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
                // 全屏
                View.SYSTEM_UI_FLAG_FULLSCREEN or
                // 隐藏导航栏
                View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

        this.decorView.systemUiVisibility = if (Build.VERSION.SDK_INT >= 19) {
            uiOptions or 0x00001000
        } else {
            uiOptions or View.SYSTEM_UI_FLAG_LOW_PROFILE
        }
    }
}

//fun Any.loge(string: String) {
//    val tag = javaClass.name.substring(javaClass.name.lastIndexOf(".") + 1)
//    Logger.e(tag, string)
//}
//
//fun Any.logd(string: String) {
//    val tag = javaClass.name.substring(javaClass.name.lastIndexOf(".") + 1)
//    Logger.d(tag, string)
//}
//
//fun Any.logd(tag : String ,string: String) {
//    Logger.d(tag, string)
//}

fun String.fileOutPutStream(): FileOutputStream {
    return FileOutputStream(this)
}

fun String.fileInputStream(): FileInputStream {
    return FileInputStream(this)
}

fun String.file(): File {
    return File(this)
}

fun File.deleteIfExists() {
    if (exists()) {
        delete()
    }
}

fun InputStream.dataInputStream(): DataInputStream {
    return DataInputStream(this)
}

fun OutputStream.dataOutputStream(): DataOutputStream {
    return DataOutputStream(this)
}

inline fun Context.registerReceiver(
    crossinline handle: (Intent?) -> Unit,
    noinline filter: IntentFilter.() -> Unit
): BroadcastReceiver {
    val receiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            handle(intent)
        }
    }
    val f = IntentFilter().apply(filter)
    this.registerReceiver(receiver, f)
    return receiver
}

fun ViewGroup.inflate(@LayoutRes layoutRes: Int, attachToRoot: Boolean = false): View {
    return LayoutInflater.from(context).inflate(layoutRes, this, attachToRoot)
}

fun Context.inflate(@LayoutRes layoutRes: Int, root: ViewGroup? = null): View {
    return LayoutInflater.from(this).inflate(layoutRes, root)
}

/**
 * 获取array.xml中的字符串资源数组string[]
 */
fun Context.getStringArray(resId: Int): Array<String> {
    return this.resources.getStringArray(resId)
}

fun Activity.getHandler(
    isMainThread: Boolean = true,
    handleMsg: Handler.(Message) -> Unit
): Handler {
    return when (isMainThread) {
        true -> {
            object : Handler(Looper.getMainLooper()) {
                override fun handleMessage(msg: Message) {
                    handleMsg(this, msg)
                }
            }
        }
        else -> {
            val mHandlerThread = HandlerThread("HandlerThread")
            mHandlerThread.start()
            object : Handler(mHandlerThread.looper) {
                override fun handleMessage(msg: Message) {
                    handleMsg(this, msg)
                }
            }
        }
    }
}

fun String.matchArray(array: Array<String>): Boolean {
    array.forEach {
        if (this.contains(it)) {
            return true
        }
    }
    return false
}

//infix fun @receiver:IntRange(from = 8400) Int.send(data: String) {
//    require(this >= 8400)
//    MsgSendUtils.sendStringMsg(
//        this,
//        data
//    )
//}
//
// fun Int.sendStringMsg(msgData: String) {
//    MsgSendUtils.sendStringMsg(
//        this, msgData
//    )
//}
//
//infix fun MsgType2.send(data: String) {
//    MsgSendUtils.sendStringMsg(
//        this.value,
//        data
//    )
//}

//fun ImageView.loadImage(
//    path: String,
//    @DrawableRes errorRes: Int = R.drawable.ic_launcher,
//    @DrawableRes holderRes: Int = R.drawable.ic_launcher
//) {
//    Glide.with(this.context).asDrawable()
//        .load(path)
//        .thumbnail(0.1f).diskCacheStrategy(DiskCacheStrategy.ALL)
//        .skipMemoryCache(false)
//        .placeholder(holderRes)
//        .error(errorRes)
//        .into(this)
//}

@OptIn(ExperimentalContracts::class)
fun CharSequence?.isNotEmpty2(): Boolean {
    contract {
        returns(true) implies (this@isNotEmpty2 != null)
    }

    return !isNullOrEmpty()
}

@OptIn(ExperimentalContracts::class)
fun <T> Collection<T>?.isNotEmpty2(): Boolean {
    contract {
        returns(true) implies (this@isNotEmpty2 != null)
    }
    return !isNullOrEmpty()
}

fun Array<*>?.isNotEmpty2(): Boolean {
    return this.isNullOrEmpty().not()
}

//fun Any.toJSONString(): String {
//    return JSONObject.toJSONString(this)
//}

fun <T> T?.orDefault(default: T): T {
    return this ?: default
}

fun View.visible() {
    this.visibility = View.VISIBLE
}

fun View.gone() {
    this.visibility = View.GONE
}

fun View.invisible() {
    this.visibility = View.INVISIBLE
}

fun View.toggleVisibility(): View = apply {
    visibility = if (visibility == View.VISIBLE) {
        View.GONE
    } else {
        View.VISIBLE
    }
}

fun Long.toCalendar(): Calendar {
    val calendar = Calendar.getInstance();
    calendar.timeInMillis = this
    return calendar
}

val Calendar.minute: Int
    get() = get(Calendar.MINUTE)

val Calendar.hour: Int
    get() = get(Calendar.HOUR_OF_DAY)

val Calendar.second: Int
    get() = get(Calendar.SECOND)

val Calendar.day: Int
    get() = get(Calendar.DAY_OF_WEEK)

val Calendar.month: Int
    get() = get(Calendar.MONTH)

val Calendar.year: Int
    get() = get(Calendar.YEAR)

val now: Calendar
    get() = Calendar.getInstance()

private fun baseDate() = Calendar.getInstance()

///**
// * 12 days ago
// */
//infix fun Int.days(ago: ago) = baseDate().also { it.add(Calendar.DAY_OF_MONTH, -this) }
//
///**
// * 12 days fromNow
// */
//infix fun Int.days(fromNow: fromNow) = baseDate().also { it.add(Calendar.DAY_OF_MONTH, this) }
//
///**
// * 2 months ago
// */
//infix fun Int.months(ago: ago) = baseDate().also { it.add(Calendar.MONTH, -this) }
//
///**
// * 2 months fromNow
// */
//infix fun Int.months(fromNow: fromNow) = baseDate().also { it.add(Calendar.MONTH, this) }
//
//inline fun assert(value: Boolean, lazyMessage: () -> Any) {
//        if (!value) {
//            val message = lazyMessage()
//            throw AssertionError(message)
//        }
//}

fun Any.toJSONString(): String {
    return JSONObject.toJSONString(this)
}
